package com.zbkj.crmeb.agent.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.crmeb.core.common.CommonResult;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.utils.CrmebUtil;
import com.zbkj.crmeb.agent.dao.AgentAccountDao;
import com.zbkj.crmeb.agent.model.Agent;
import com.zbkj.crmeb.agent.model.AgentAccount;
import com.zbkj.crmeb.agent.model.AgentAccountFlow;
import com.zbkj.crmeb.agent.request.AgentAccountCenterRequest;
import com.zbkj.crmeb.agent.service.AgentAccountFlowService;
import com.zbkj.crmeb.agent.service.AgentAccountService;
import com.zbkj.crmeb.agent.service.AgentService;
import com.zbkj.crmeb.chant.response.AccountCenterResponse;
import com.zbkj.crmeb.chant.response.AccountCenterResponse.Bill;
import com.zbkj.crmeb.enums.AccountFlowTypeEnum;
import com.zbkj.crmeb.finance.controller.WithdrawalAuditRequest;
import com.zbkj.crmeb.finance.model.UserRecharge;
import com.zbkj.crmeb.finance.response.UserRechargeResponse;
import com.zbkj.crmeb.finance.service.UserRechargeService;
import com.zbkj.crmeb.merchant.admin.service.MerAgentStoreOrderService;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreOrderInfo;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.service.StoreOrderInfoService;
import com.zbkj.crmeb.store.service.StoreOrderService;
import com.zbkj.crmeb.store.vo.StoreOrderInfoVo;
import com.zbkj.crmeb.system.service.SystemAdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务商资金账户表 服务实现类
 * </p>
 *
 * @author wuzp
 * @since 2022-02-15
 */
@Service
@Slf4j
public class AgentAccountServiceImpl extends ServiceImpl<AgentAccountDao, AgentAccount> implements AgentAccountService {

    @Autowired
    AgentAccountDao agentAccountDao;
    @Autowired
    SystemAdminService systemAdminService;
    @Autowired
    AgentAccountFlowService agentAccountFlowService;
    @Autowired
    UserRechargeService userRechargeService;
    @Autowired
    StoreOrderService storeOrderService;
    @Autowired
    StoreOrderInfoService storeOrderInfoService;
    @Autowired
    AgentService agentService;
    @Autowired
    MerAgentStoreOrderService merAgentStoreOrderService;


    @Override
    public Integer calcMoney(AgentAccount entity) {
        AgentAccount agentAccount = getOne(Wrappers.<AgentAccount>lambdaQuery().eq(AgentAccount::getAgentId, entity.getAgentId()));
        boolean b = false;
        //是否执行修改sql  true直接跳过
        boolean flag = true;
        // 金额校验
        if (null != entity.getWithdrawAccount()) {
            if(BigDecimal.ZERO.compareTo(agentAccount.getWithdrawAccount().add(entity.getWithdrawAccount())) > 0){
                b = true;
            }
            if(BigDecimal.ZERO.compareTo(entity.getWithdrawAccount()) != 0){
                flag = false;
            }
        }
        if (null != entity.getFreezeAccount()) {
            if(BigDecimal.ZERO.compareTo(agentAccount.getFreezeAccount().add(entity.getFreezeAccount())) > 0){
                b = true;
            }
            if(BigDecimal.ZERO.compareTo(entity.getFreezeAccount()) != 0){
                flag = false;
            }
        }
        if (null != entity.getTotalMoney()) {
            if(BigDecimal.ZERO.compareTo(agentAccount.getTotalMoney().add(entity.getTotalMoney())) > 0){
                b = true;
            }
            if(BigDecimal.ZERO.compareTo(entity.getTotalMoney()) != 0){
                flag = false;
            }
        }
        if (null != entity.getCloseMoney()) {
            if(BigDecimal.ZERO.compareTo(agentAccount.getCloseMoney().add(entity.getCloseMoney())) > 0){
                b = true;
            }
            if(BigDecimal.ZERO.compareTo(entity.getCloseMoney()) != 0){
                flag = false;
            }
        }
        if (b) {
            throw new CrmebException("账户余额不足!");
        }
        if(flag){
            return 1;
        }
        return agentAccountDao.calcMoney(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean offlineWithdrawApply(Integer agentId, BigDecimal price, String ip) {
        AgentAccount agentAccount = this.getOne(Wrappers.<AgentAccount>lambdaQuery()
                .eq(AgentAccount :: getAgentId, agentId)
        );
        if(agentAccount == null){
            throw new CrmebException("该服务商不存在!");
        }
        if(StringUtils.isBlank(agentAccount.getCreateBank()) || StringUtils.isBlank(agentAccount.getBankName()) || StringUtils.isBlank(agentAccount.getBankNo())){
            throw new CrmebException("服务商收款信息异常!");
        }
        if(agentAccount.getStatus() == 1){
            throw new CrmebException("服务商账户已冻结,不可申请提现");
        }
        // 生成提现记录
        int id = systemAdminService.getAdminId();
        String orderId = CrmebUtil.getOrderNo(Constants.PAY_TYPE_WE_CHAT);
        UserRecharge userRecharge = new UserRecharge();
        userRecharge.setUid(id);
        userRecharge.setAgentId(agentId);
        userRecharge.setOrderId(orderId);
        userRecharge.setPrice(price);
        userRecharge.setStatus(0);
        userRecharge.setTradeType(2); // 提现
        userRecharge.setPaid(false);
        userRecharge.setBankName(agentAccount.getBankName());
        userRecharge.setBankNo(agentAccount.getBankNo());
        userRecharge.setCreateBank(agentAccount.getCreateBank());
        userRecharge.setIp(ip);
        userRecharge.setCreateTime(new Date());
        userRecharge.setUpdateTime(new Date());
        userRechargeService.save(userRecharge);

        // 可提现余额冻结
        AgentAccount account = new AgentAccount();
        account.setAgentId(agentId);
        account.setWithdrawAccount(price.negate());
        account.setFreezeAccount(price);
        this.calcMoney(account);

        // 流水操作
        agentAccountFlowService.saveAccountFlow(agentId, userRecharge.getId(), id, ip, AccountFlowTypeEnum.RECHARGE, price.negate(), price, "服务商申请提现");

        log.info("服务商: {} 申请提现: {} ip: {}", agentId, price, ip);

        return true;
    }

    @Override
    public AccountCenterResponse agentAccountCenter(AgentAccountCenterRequest request) {
        AccountCenterResponse accountCenterResponse = new AccountCenterResponse();
        //头部数据
        AgentAccount agentAccount = this.getOne(Wrappers.<AgentAccount>lambdaQuery().eq(AgentAccount::getAgentId, request.getAgentId()).last("LIMIT 1"));
        if(Objects.isNull(agentAccount)){
            throw new CrmebException("该服务商不存在!");
        }
        BeanUtils.copyProperties(agentAccount,accountCenterResponse);
        //列表数据
        Page<Bill> billPage = PageHelper.startPage(request.getPage(), request.getLimit());
        List<Bill> collect = getFlowList(request.getAgentId(),request.getType());
        accountCenterResponse.setOrderList(CommonPage.restPage(CommonPage.copyPageInfo(billPage, collect)));
        return accountCenterResponse;
    }

    @Override
    public boolean accountFrozen(Integer id, Integer status) {
        AgentAccount agentAccount = this.getOne(Wrappers.<AgentAccount>lambdaQuery().eq(AgentAccount::getAgentId, id).last("LIMIT 1"));
        if(agentAccount == null){
            throw new CrmebException("该服务商不存在!");
        }
        if(agentAccount.getStatus().equals(status)){
            throw new CrmebException("参数异常!");
        }
        agentAccount.setStatus(status);
        return this.updateById(agentAccount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Object> offlineWithdrawAudit(WithdrawalAuditRequest req, String clientIp) {
        UserRecharge userRecharge = userRechargeService.getById(req.getId());
        if(null == userRecharge) {
            return CommonResult.failed("该记录不存在!");
        }
        if(0 != userRecharge.getStatus()) {
            return CommonResult.failed("该记录已处理!");
        }
        if(-1 != req.getStatus() && 1 != req.getStatus()) {
            return CommonResult.failed("审核状态错误!");
        }
        if(2 != userRecharge.getTradeType()) {
            return CommonResult.failed("该记录非提现申请!");
        }
        if(1 == req.getStatus() && req.getPaymentAmount() == null){
            return CommonResult.failed("付款金额不能为空!");
        }
        int id = systemAdminService.getAdminId();
        log.info("审核服务商: {} 提现申请: {} ip: {}, status: {}, adminId: {}", userRecharge.getMerId(), userRecharge.getPrice(), clientIp, req.getStatus(), id);
        // 资金操作
        AgentAccount agentAccount = new AgentAccount();
        agentAccount.setAgentId(userRecharge.getAgentId());
        agentAccount.setFreezeAccount(userRecharge.getPrice().negate());
        if (-1 == req.getStatus()) {
            agentAccount.setWithdrawAccount(userRecharge.getPrice());
        }
        if(1 == req.getStatus()){
            agentAccount.setCloseMoney(userRecharge.getPrice());
        }
        this.calcMoney(agentAccount);
        // 更改订单
        userRechargeService.update(Wrappers.<UserRecharge>lambdaUpdate()
                .eq(UserRecharge :: getId, userRecharge.getId())
                .set(UserRecharge :: getStatus, req.getStatus())
                .set(UserRecharge :: getPaid, true)
                .set(UserRecharge :: getPayTime, new Date())
                .set(UserRecharge::getPaymentAmount,req.getPaymentAmount())
                .set(UserRecharge::getCredentials,CollectionUtils.isNotEmpty(req.getUrlList()) ?String.join(",", req.getUrlList()):null)
        );
        // 流水操作
        agentAccountFlowService.saveAccountFlow(userRecharge.getAgentId(), userRecharge.getId(), id, clientIp, AccountFlowTypeEnum.RECHARGE,
                 agentAccount.getWithdrawAccount(),agentAccount.getFreezeAccount(), "服务商提现审核");
        return CommonResult.success();
    }

    @Override
    public Object accountInfo(Integer id) {
        AgentAccountFlow accountFlow = getAgentAccountFlow(id);
        if (accountFlow == null) {
            return null;
        }
        return AccountFlowTypeEnum.PRODUCT.getCode().equals(accountFlow.getTradeType()) ? storeOrderService.info(accountFlow.getOtId())
                : this.getRechargeInfo(accountFlow.getOtId());
    }

    public AgentAccountFlow getAgentAccountFlow(Integer id) {
        AgentAccountFlow accountFlow = agentAccountFlowService.getById(id);
        if (null == accountFlow) {
            throw new CrmebException("该笔流水不存在!");
        }
        if (accountFlow.getOtId() == null) {
            return null;
        }
        return accountFlow;
    }

    @Override
    public UserRechargeResponse getRechargeInfo(Integer id) {
        UserRecharge userRecharge = userRechargeService.getById(id);
        if(userRecharge == null){
            throw new CrmebException("记录不存在!");
        }
        UserRechargeResponse userRechargeResponse = new UserRechargeResponse();
        BeanUtils.copyProperties(userRecharge, userRechargeResponse);
        Agent agent = agentService.getById(userRecharge.getAgentId());
        if(agent != null){
            userRechargeResponse.setAgentName(agent.getAgentName());
            userRechargeResponse.setAgentCreateTime(agent.getCreateTime());
        }
        userRechargeResponse.setUrlList(org.apache.commons.lang3.StringUtils.isNotBlank(userRecharge.getCredentials()) ? Arrays.asList(userRecharge.getCredentials().split(",")):null);
        return userRechargeResponse;
    }

    @Override
    public List<Bill> getFlowList(Integer merId, Integer type) {
        LambdaQueryWrapper<AgentAccountFlow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AgentAccountFlow::getAgentId,merId).orderByDesc(AgentAccountFlow::getId);
        switch (type) {
            case 2:
                //可提现余额
                lambdaQueryWrapper.isNotNull(AgentAccountFlow::getWithdrawAccount);
                break;
            case 3:
                //冻结金额
                lambdaQueryWrapper.isNotNull(AgentAccountFlow::getFreezeAccount);
                break;
            default:
                break;
        }
        List<AgentAccountFlow> agentAccountFlowList = agentAccountFlowService.list(lambdaQueryWrapper);
        //返回数据处理
        return agentAccountFlowList.stream().map(e -> {
            Bill bill = new Bill().setBillId(e.getId()).setCreateTime(e.getCreateTime())
                    .setOrderDetail(e.getRemark()).setTradeType(e.getTradeType());
            if (type == 2) {
                bill.setMoney(e.getWithdrawAccount());
                bill.setResidueMoney(e.getNowWithdrawAccount());
            } else if (type == 3) {
                bill.setMoney(e.getFreezeAccount());
                bill.setResidueMoney(e.getNowFreezeAccount());
            }
            if(bill.getMoney().compareTo(BigDecimal.ZERO) == 0){
                bill.setType(bill.getOrderDetail().contains("退款") ? "支出" : "收入");
            }else {
                bill.setType(bill.getMoney().compareTo(BigDecimal.ZERO) < 0 ? "支出" : "收入");
            }
            bill.setMoney(bill.getMoney().abs());
            String orderId;
            if (AccountFlowTypeEnum.PRODUCT.getCode().equals(e.getTradeType())) {
                orderId = Optional.ofNullable(storeOrderService.getById(e.getOtId())).orElse(new StoreOrder()).getOrderId();
                //订单表
                List<StoreOrderInfo> list = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery().eq(StoreOrderInfo::getOrderId, e.getOtId()));
                List<StoreOrderInfoVo> storeOrderInfoVoList = new ArrayList<>();
                //商品详情
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(order -> {
                        StoreOrderInfoVo StoreOrderInfoVo = new StoreOrderInfoVo();
                        BeanUtils.copyProperties(order, StoreOrderInfoVo, "info");
                        StoreOrderInfoVo.setInfo(JSON.parseObject(order.getInfo(), StoreCartResponse.class));
                        storeOrderInfoVoList.add(StoreOrderInfoVo);
                    });
                }
                bill.setProductList(storeOrderInfoVoList);
            }else {
                orderId = Optional.ofNullable(userRechargeService.getById(e.getOtId())).orElse(new UserRecharge()).getOrderId();
            }
            bill.setOrderId(orderId);
            return bill;
        }).collect(Collectors.toList());
    }

    @Override
    public Object agentAccountInfo(Integer id) {
        AgentAccountFlow accountFlow = getAgentAccountFlow(id);
        if (accountFlow == null){
            return null;
        }
        return AccountFlowTypeEnum.PRODUCT.getCode().equals(accountFlow.getTradeType()) ? merAgentStoreOrderService.info(accountFlow.getOtId())
                : this.getRechargeInfo(accountFlow.getOtId());
    }


}
